package com.salesmanager.web.shop.relanishment;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.salesmanager.core.business.catalog.product.model.Product;
import com.salesmanager.core.business.catalog.product.model.ProductCriteria;
import com.salesmanager.core.business.catalog.product.service.PricingService;
import com.salesmanager.core.business.catalog.product.service.ProductService;
import com.salesmanager.core.business.customer.model.Customer;
import com.salesmanager.core.business.generic.exception.ConversionException;
import com.salesmanager.core.business.generic.exception.ServiceException;
import com.salesmanager.core.business.merchant.model.MerchantStore;
import com.salesmanager.core.business.order.model.Order;
import com.salesmanager.core.business.order.model.OrderCriteria;
import com.salesmanager.core.business.order.model.orderproduct.OrderProduct;
import com.salesmanager.core.business.order.service.OrderService;
import com.salesmanager.core.business.reference.language.model.Language;
import com.salesmanager.web.entity.catalog.ProductList;
import com.salesmanager.web.entity.catalog.product.ReadableProduct;
import com.salesmanager.web.populator.catalog.ReadableProductPopulator;

public class ReplanishmentPlanner {

		
	public ProductList getRecomendedItems(OrderService orderService, ProductService productService, Customer customer, MerchantStore store, Language lang, PricingService pricingService) throws ServiceException {
		
		OrderCriteria criteria = new OrderCriteria();
		
		if(!StringUtils.isBlank(customer.getNick())) {
			criteria.setCustomerName(customer.getNick());
		}
		
		List<Order> orderList = orderService.getOrderByCustomer(store, customer);
		
		ProductList recomendedProducts = null;
		
		if(orderList.size() > 0) {
			try {
				recomendedProducts = getRecomProductList(orderList, store, productService, lang, pricingService);
			} catch (ConversionException e) {
				e.printStackTrace();
			}
		}
		
		return recomendedProducts;
	}
	
	
	private ProductList getRecomProductList(List<Order> orderList, MerchantStore store, ProductService productService, Language lang, PricingService pricingService) throws ConversionException {
		
		Map<String, Integer> productCountMap = getProductCountMap(orderList);
		
		
		ProductCriteria productCriteria = new ProductCriteria();
		
		List<String> skuList = new ArrayList<String>();
		skuList.addAll(productCountMap.keySet());
		
		productCriteria.setSkuList(skuList);
		
		com.salesmanager.core.business.catalog.product.model.ProductList products = productService.listByStore(store, lang, productCriteria);

		ReadableProductPopulator populator = new ReadableProductPopulator();
		populator.setPricingService(pricingService);
		
		
		ProductList productList = new ProductList();
		for(Product product : products.getProducts()) {

			//create new proxy product
			ReadableProduct  p = populator.populate(product, new ReadableProduct(), store, lang);
			productList.getProducts().add(p);
			
		}
		
		productList.setProductCount(products.getTotalCount());
		return productList;
		
		
		
		/*ShopProductController spc = new ShopProductController();
		
		return productService.getProductsListBySku(productCountMap.keySet(), store);*/
	}
	
	
	private Map<String, Integer> getProductCountMap(List<Order> orderList) {
		
		Map<String, Integer> productCountMap = new HashMap<String, Integer>();
		
		for(int i = 0; i < 5; i++) {
			
			if(orderList.get(i).getOrderProducts().size() > 0) {
				for(OrderProduct op: orderList.get(i).getOrderProducts()) {
					
					int productCounter = 0;
					
					if(productCountMap.containsKey(op.getSku())) {
						productCounter = productCountMap.get(op.getSku()) + 1;
						productCountMap.put(op.getSku(), productCounter);
					} else {
						productCountMap.put(op.getSku(), ++productCounter);
					}
				}
			}
		}
		
		productCountMap = MapUtil.sortByValue(productCountMap);
		
		return productCountMap;
	}
	
	
	
	static class MapUtil
	{
	    public static <K, V extends Comparable<? super V>> Map<K, V> 
	        sortByValue( Map<K, V> map )
	    {
	        List<Map.Entry<K, V>> list =
	            new LinkedList<Map.Entry<K, V>>( map.entrySet() );
	        Collections.sort( list, new Comparator<Map.Entry<K, V>>()
	        {
	            public int compare( Map.Entry<K, V> o1, Map.Entry<K, V> o2 )
	            {
	                return (o2.getValue()).compareTo( o1.getValue() );
	            }
	        } );

	        Map<K, V> result = new LinkedHashMap<K, V>();
	        for (Map.Entry<K, V> entry : list)
	        {
	            result.put( entry.getKey(), entry.getValue() );
	        }
	        return result;
	    }
	}
}
